

#include <stdint.h>
#include <stdbool.h>



typedef struct {
    uint64_t smoothed_value;
    bool initialized;
} exp_avg_t;

// Alpha = 1/2^shift (např. shift=3 -> alpha=1/8=0.125)
#define EXP_AVG_SHIFT 2  // Alpha = 1/16 = 0.0625

void exp_avg_init(exp_avg_t* avg) {
    avg->smoothed_value = 0;
    avg->initialized = false;
}

uint64_t exp_avg_update(exp_avg_t* avg, uint64_t new_value) {
    if (!avg->initialized) {
        avg->smoothed_value = new_value;
        avg->initialized = true;
        return new_value;
    }
    
    // smoothed = (1-alpha)*smoothed + alpha*new_value
    // Použití bit-shift místo float aritmetiky
    avg->smoothed_value = avg->smoothed_value - (avg->smoothed_value >> EXP_AVG_SHIFT) + 
                         (new_value >> EXP_AVG_SHIFT);
    
    return avg->smoothed_value;
}






#define BUFFER_SIZE_BITS 4  // 2^4 = 16 vzorků
#define BUFFER_SIZE (1 << BUFFER_SIZE_BITS)
#define BUFFER_MASK (BUFFER_SIZE - 1)

typedef struct {
    uint64_t buffer[BUFFER_SIZE];
    uint64_t sum;
    uint8_t index;
    uint8_t count;
} ring_avg_t;

void ring_avg_init(ring_avg_t* avg) {
    for (int i = 0; i < BUFFER_SIZE; i++) {
        avg->buffer[i] = 0;
    }
    avg->sum = 0;
    avg->index = 0;
    avg->count = 0;
}

uint64_t ring_avg_update(ring_avg_t* avg, uint64_t new_value) {
    // Odečti starý vzorek, přidej nový
    avg->sum -= avg->buffer[avg->index];
    avg->buffer[avg->index] = new_value;
    avg->sum += new_value;
    
    avg->index = (avg->index + 1) & BUFFER_MASK;  // Rychlé modulo pomocí AND
    
    if (avg->count < BUFFER_SIZE) {
        avg->count++;
    }
    
    // Rychlé dělení pomocí bit-shift (protože BUFFER_SIZE je mocnina 2)
    return avg->sum >> BUFFER_SIZE_BITS;
}

// =============================================================================
// 3. ADAPTIVNÍ PRŮMĚR S OUTLIER DETEKCÍ (nejstabilnější)
// =============================================================================

typedef struct {
    uint64_t current_avg;
    uint64_t min_threshold;
    uint64_t max_threshold;
    uint8_t outlier_count;
    bool initialized;
} adaptive_avg_t;

#define OUTLIER_THRESHOLD_PERCENT 8 // ±20% tolerance
#define MAX_OUTLIERS 3  // Maximální počet outlierů v řadě

void adaptive_avg_init(adaptive_avg_t* avg, uint64_t initial_estimate) {
    avg->current_avg = initial_estimate;
    avg->min_threshold = initial_estimate * (100 - OUTLIER_THRESHOLD_PERCENT) / 100;
    avg->max_threshold = initial_estimate * (100 + OUTLIER_THRESHOLD_PERCENT) / 100;
    avg->outlier_count = 0;
    avg->initialized = true;
}

uint64_t adaptive_avg_update(adaptive_avg_t* avg, uint64_t new_value) {
    if (!avg->initialized) {
        adaptive_avg_init(avg, new_value);
        return new_value;
    }
    
    // Kontrola outlierů
    if (new_value < avg->min_threshold || new_value > avg->max_threshold) {
        avg->outlier_count++;
        
        // Pokud je příliš mnoho outlierů, přizpůsob se
        if (avg->outlier_count >= MAX_OUTLIERS) {
            // Pomalu se adaptuj na novou hodnotu
            avg->current_avg = (avg->current_avg * 7 + new_value) >> 3;  // 7/8 old + 1/8 new
            
            // Aktualizuj prahy
            avg->min_threshold = avg->current_avg * (100 - OUTLIER_THRESHOLD_PERCENT) / 100;
            avg->max_threshold = avg->current_avg * (100 + OUTLIER_THRESHOLD_PERCENT) / 100;
            avg->outlier_count = 0;
        }
        // Jinak ignoruj outlier
        
        return avg->current_avg;
    }
    
    // Normální hodnota - rychlá adaptace
    avg->outlier_count = 0;
    avg->current_avg = (avg->current_avg * 15 + new_value) >> 4;  // 15/16 old + 1/16 new
    
    // Aktualizuj prahy
    avg->min_threshold = avg->current_avg * (100 - OUTLIER_THRESHOLD_PERCENT) / 100;
    avg->max_threshold = avg->current_avg * (100 + OUTLIER_THRESHOLD_PERCENT) / 100;
    
    return avg->current_avg;
}

// =============================================================================
// 4. OPTIMALIZOVANÝ MEDIÁN (pro extrémní stabilitu)
// =============================================================================

#define MEDIAN_SIZE 5

typedef struct {
    uint64_t buffer[MEDIAN_SIZE];
    uint8_t index;
    uint8_t count;
} median_filter_t;

void median_init(median_filter_t* med) {
    for (int i = 0; i < MEDIAN_SIZE; i++) {
        med->buffer[i] = 0;
    }
    med->index = 0;
    med->count = 0;
}

// Rychlé insertion sort pro malé pole
static uint64_t quick_median(uint64_t arr[], uint8_t size) {
    // Jednoduchý insertion sort
    for (int i = 1; i < size; i++) {
        uint64_t key = arr[i];
        int j = i - 1;
        while (j >= 0 && arr[j] > key) {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = key;
    }
    return arr[size / 2];  // Střední hodnota
}

uint64_t median_update(median_filter_t* med, uint64_t new_value) {
    med->buffer[med->index] = new_value;
    med->index = (med->index + 1) % MEDIAN_SIZE;
    
    if (med->count < MEDIAN_SIZE) {
        med->count++;
    }
    
    // Zkopíruj buffer pro sorting (zachovej originál)
    uint64_t temp[MEDIAN_SIZE];
    for (int i = 0; i < med->count; i++) {
        temp[i] = med->buffer[i];
    }
    
    return quick_median(temp, med->count);
}